
package com.echo.sdk.im.config;

import cn.hutool.core.map.MapUtil;
import com.echo.sdk.im.constant.CIMConstant;
import com.echo.sdk.im.constant.properties.CIMProperties;
import com.echo.sdk.im.enums.SocketHandlerEnum;
import com.echo.sdk.im.handler.CIMRequestHandler;
import com.echo.sdk.im.handler.SessionClosedHandler;
import com.echo.sdk.im.server.CIMNioSocketServer;
import com.echo.sdk.im.handler.AuthorizationHandler;
import com.echo.sdk.im.model.CIMSession;
import com.echo.sdk.im.model.CIMMsg;
import com.echo.sdk.im.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author chentl
 * @Version V1.0
 * @Project wh-bigdata-frame.
 * @Title CIMConfig
 * @Description CIM 启动配置类
 * @Package com.echo.sdk.im.server.config
 * @Date 2021/6/18 3:30 下午
 */
@Slf4j
@Configuration
public class CIMConfig implements CIMRequestHandler, ApplicationListener<ApplicationStartedEvent> {

    @Resource
    private ApplicationContext applicationContext;

    @Resource
    private CIMProperties cimProperties;


    private final HashMap<String, CIMRequestHandler> webHandlerMap = new HashMap<>();


    @Bean(destroyMethod = "destroy")
    public CIMNioSocketServer getNioSocketServer() {
        if (StringUtils.isEmpty(cimProperties.getHost()))
            throw new RuntimeException("cim.host can not be empty,please check your configuration!");
        if (cimProperties.getPort() == CIMConstant.DEFAULT_PORT)
            log.warn("cim used default port:" + CIMConstant.DEFAULT_PORT);


        return new CIMNioSocketServer.Builder()
                .setWebsocketConfig(cimProperties.getHost(), cimProperties.getPort())
                .setOuterRequestHandler(this)
                .build();

    }

    @Override
    public void process(CIMSession session, CIMMsg body) {
        CIMRequestHandler handler = webHandlerMap.get(body.getType());
        if (handler == null) {
            return;
        }
        handler.process(session, body);
    }

    /*
     * springboot启动完成之后再启动cim服务的，避免服务正在重启时，客户端会立即开始连接导致意外异常发生.
     */
    @Override
    public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {

        try {
            // 从配置文件读取handler 并加载指定handler。
            Map<String, String> hanlderMap = cimProperties.getHandlerMap();
            if (MapUtil.isNotEmpty(hanlderMap)) {
                hanlderMap.forEach((theme, handler) -> {
                    try {
                        Class<CIMRequestHandler> handlerClass = (Class<CIMRequestHandler>) Class.forName(handler);
                        webHandlerMap.put(theme, applicationContext.getBean(handlerClass));
                    } catch (ClassNotFoundException e) {
                        log.error("[cim] 动态加载handler时发生异常");
                    }
                });
            }

            webHandlerMap.put(SocketHandlerEnum.CLIENT_AUTHORIZATION.getCode(), applicationContext.getBean(AuthorizationHandler.class));
            webHandlerMap.put(SocketHandlerEnum.CLIENT_CLOSED.getCode(), applicationContext.getBean(SessionClosedHandler.class));

            applicationContext.getBean(CIMNioSocketServer.class).bind();
        } catch (Exception e) {
            log.error("[cim] 绑定handler时出现异常");
        }
    }
}